/*
 * Copyright (c) 2010 Zauber S.A.  -- All rights reserved
 */
package ar.edu.itba.ia2010.geneticos.motor.api.impl;

import org.apache.commons.lang.Validate;

import ar.edu.itba.ia2010.geneticos.motor.api.CacheableCromosoma;
import ar.edu.itba.ia2010.geneticos.motor.api.Cromosoma;
import ar.edu.itba.ia2010.geneticos.motor.api.FuncionAptitud;

/**
 * Clase base para funciones de aptitud
 * 
 * @author Juan F. Codagnone
 * @since Apr 2, 2010
 * @param <T> tipo del gen
 */
public class CacheableFuncionAptitudDecorator<T> implements FuncionAptitud<T> {
    private final FuncionAptitud<T> target;

    /** Creates the CacheableFuncionAptitudDecorator. */
    public CacheableFuncionAptitudDecorator(final FuncionAptitud<T> target) {
        Validate.notNull(target);
        
        this.target = target;
    }
    
    /** @see FuncionAptitud#calcularAptitud(Cromosoma) */
    @SuppressWarnings("unchecked")
    public final double calcularAptitud(final Cromosoma<T> individuo) {
        Double ret = null;
        if(individuo instanceof CacheableCromosoma) {
            ret = ((CacheableCromosoma)individuo).getAptitud();
        }
        
//        checkCache(individuo);
        if(ret == null) {
            ret = target.calcularAptitud(individuo);
            if(individuo instanceof CacheableCromosoma) {
                ((CacheableCromosoma)individuo).setAptitud(ret);
            }
        }
        return ret;
    }

    /** verifica que la invalidacion de cache funcione */
    private void checkCache(final Cromosoma<T> individuo) {
        if(individuo instanceof CacheableCromosoma) {
            final double d = target.calcularAptitud(individuo);
            final Double t = ((CacheableCromosoma)individuo).getAptitud();
             
            if(t != null) {
                if(Math.abs(d - t) >= 0.00001) {
                    throw new IllegalStateException("missmatch: "
                            + d + " " + t + " -- " + (d - t)
                            + " " + individuo);
                }
            }
        }
    }
}
